package net.oschina.git.zengzhihao.two;

import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

/**
 * 界面布局
 * 
 * @author zengzhihao
 */
public class LaunchFrame extends JFrame implements ActionListener {

	private static final long serialVersionUID = 1L;

	private JFrame frame;
	private Container container;
	private JPanel leftPanel;
	private JLabel job;
	private JLabel process;
	private JButton launchButton;
	private JPanel rightPanel;
	private JButton randButton;
	private String[][] randRows;
	private List<JCB> jcbs;
	private DefaultTableModel randTableModel;
	private DefaultTableCellRenderer randTableCellRenderer;
	private JTable randTable;
	private JPanel centerPanel;
	private String[][] resultRows;
	private String[] resultColumns;
	private DefaultTableCellRenderer resultableCellRenderer;
	private JTable resultTable;
	private DefaultTableModel defaultTableModel;
	private String[] randColumns;
	private JPanel readyPanel;
	private String[][] readyRows;
	private String[] readyColumns;
	private DefaultTableCellRenderer readyTableCellRenderer;
	private JTable readyTable;
	private DefaultTableModel readyTableModel;
	private JPanel processPanel;
	private String[][] processRows;
	private String[] processColumns;
	private DefaultTableCellRenderer processTableCellRenderer;
	private JTable processTable;
	private DefaultTableModel processTableModel;
	private JLabel ZZ;
	private JLabel DQZZ;
	private JTextField avgZZ;
	private JTextField avgDQZZ;
	private boolean clicked = false;
	private static int time = 0;
	private static int runTime = 0;
	private static int resultTableUpdate = 0;
	private List<JCB> jcbList = new ArrayList<JCB>();
	private List<JCB> readyJcbs = new ArrayList<JCB>();
	private List<JCB> processJcbs = new ArrayList<JCB>();
	private JCB runJcb;
	private boolean finished = false;
	private static int num = 0;

	/**
	 * 初始化主界面
	 */
	@SuppressWarnings("serial")
	public void init() {
		frame = new JFrame("3111006217---曾治浩---两道批处理系统的两级调度");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLayout(null);
		frame.setBounds(400, 3, 720, 720);
		frame.setResizable(false);
		container = frame.getContentPane();

		leftPanel = new JPanel();
		leftPanel.setBounds(30, 50, 250, 100);
		leftPanel.setBorder(BorderFactory.createTitledBorder("调度算法"));
		job = new JLabel("作业调度采用先来先服务算法");
		process = new JLabel("进程调度采用可抢占的优先级调度算法");
		launchButton = new JButton("运行");
		launchButton.addActionListener(this);
		leftPanel.add(job);
		leftPanel.add(process);
		leftPanel.add(launchButton);
		container.add(leftPanel);

		rightPanel = new JPanel();
		rightPanel.setBounds(300, 10, 380, 170);
		rightPanel.setBorder(BorderFactory.createTitledBorder("分配作业"));
		randButton = new JButton("点击分配");
		randButton.addActionListener(this);
		randRows = new String[4][4];
		randColumns = new String[] { "作业名称", "到达时间", "服务时间", "优先数" };
		randTableModel = new DefaultTableModel(randRows, randColumns);
		randTableCellRenderer = new DefaultTableCellRenderer();
		randTableCellRenderer.setHorizontalAlignment(JLabel.CENTER);
		randTable = new JTable(randTableModel) {
			@Override
			public boolean isCellEditable(int row, int column) {
				return false;
			}
		};
		randTable.setRowHeight(20);
		randTable.setDefaultRenderer(Object.class, randTableCellRenderer);
		rightPanel.add(randTable.getTableHeader());
		rightPanel.add(randTable);
		rightPanel.add(randButton);
		container.add(rightPanel);

		processPanel = new JPanel();
		processPanel.setBounds(80, 200, 530, 100);
		processPanel.setBorder(BorderFactory.createTitledBorder("正在运行进程"));
		processRows = new String[1][6];
		processColumns = new String[] { "作业名称", "服务时间", "开始执行时间", "已执行时间",
				"还需执行时间", "优先权" };
		processTableModel = new DefaultTableModel(processRows, processColumns);
		processTableCellRenderer = new DefaultTableCellRenderer();
		processTableCellRenderer.setHorizontalAlignment(JLabel.CENTER);
		processTable = new JTable(processTableModel) {
			@Override
			public boolean isCellEditable(int row, int column) {
				return false;
			}
		};
		processTable.setDefaultRenderer(Object.class, processTableCellRenderer);
		processTable.setRowHeight(30);
		processPanel.add(processTable.getTableHeader());
		processPanel.add(processTable);
		container.add(processPanel);

		readyPanel = new JPanel();
		readyPanel.setBounds(100, 320, 500, 130);
		readyPanel.setBorder(BorderFactory.createTitledBorder("内存就绪进程"));
		readyRows = new String[2][4];
		readyColumns = new String[] { "作业名称", "服务时间", "优先权", "状态" };
		readyTableModel = new DefaultTableModel(readyRows, readyColumns);
		readyTableCellRenderer = new DefaultTableCellRenderer();
		readyTableCellRenderer.setHorizontalAlignment(JLabel.CENTER);
		readyTable = new JTable(readyTableModel) {
			@Override
			public boolean isCellEditable(int row, int column) {
				return false;
			}
		};
		readyTable.setDefaultRenderer(Object.class, readyTableCellRenderer);
		readyTable.setRowHeight(30);
		readyPanel.add(readyTable.getTableHeader());
		readyPanel.add(readyTable);
		container.add(readyPanel);

		centerPanel = new JPanel();
		centerPanel.setBounds(10, 470, 700, 200);
		centerPanel.setBorder(BorderFactory.createTitledBorder("外存就绪作业"));
		resultRows = new String[4][9];
		resultColumns = new String[] { "作业名称", "到达时间", "服务时间", "开始执行时间",
				"完成时间", "优先权", "状态", "周转时间", "带权周转时间" };
		defaultTableModel = new DefaultTableModel(resultRows, resultColumns);
		resultableCellRenderer = new DefaultTableCellRenderer();
		resultableCellRenderer.setHorizontalAlignment(JLabel.CENTER);
		resultTable = new JTable(defaultTableModel) {
			@Override
			public boolean isCellEditable(int row, int column) {
				return false;
			}
		};
		resultTable.setDefaultRenderer(Object.class, resultableCellRenderer);
		resultTable.setRowHeight(30);
		centerPanel.add(resultTable.getTableHeader());
		centerPanel.add(resultTable);
		ZZ = new JLabel("平均周转时间:");
		DQZZ = new JLabel("平均带权周转时间:");
		avgZZ = new JTextField(5);
		avgZZ.setEditable(false);
		avgZZ.setHorizontalAlignment(JTextField.CENTER);
		avgZZ.setForeground(Color.RED);
		avgDQZZ = new JTextField(5);
		avgDQZZ.setEditable(false);
		avgDQZZ.setHorizontalAlignment(JTextField.CENTER);
		avgDQZZ.setForeground(Color.RED);
		centerPanel.add(ZZ);
		centerPanel.add(avgZZ);
		centerPanel.add(DQZZ);
		centerPanel.add(avgDQZZ);
		container.add(centerPanel);

		// 界面显示完整
		frame.setVisible(true);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == launchButton) {
			if (!clicked) {
				JOptionPane.showMessageDialog(null, "请分配作业", "温馨提示",
						JOptionPane.INFORMATION_MESSAGE);
				return;
			}
			if (finished) {
				JOptionPane.showMessageDialog(null, "已完成作业调度", "温馨提示",
						JOptionPane.INFORMATION_MESSAGE);
				return;
			}
			FCFS.fcfs(jcbs);
			final Timer resultTableTimer = new Timer();
			resultTableTimer.schedule(new TimerTask() {
				@Override
				public void run() {

					if (resultTableUpdate < 4) {
						for (int i = 0; i < 4; i++) {
							if (jcbs.get(i).getArrivalTime() == time) {
								jcbList.add(jcbs.get(i));
								// 内存就绪进程
								if (jcbList.size() > 0) {
									if (readyJcbs != null
											&& readyJcbs.size() < 3) {
										readyJcbs = jcbList;
										resetReadyTableData();
									}
								}

								// 外存就绪作业
								resultRows[i][0] = jcbs.get(i).getName();
								resultRows[i][1] = jcbs.get(i).getArrivalTime()
										.toString();
								resultRows[i][2] = jcbs.get(i).getServiceTime()
										.toString();
								resultRows[i][5] = jcbs.get(i).getPriority()
										.toString();
								if (readyJcbs != null && readyJcbs.size() < 3) {
									resultRows[i][6] = jcbs.get(i).getStatus();
								} else {
									jcbs.get(i).setStatus("W");
									resultRows[i][6] = jcbs.get(i).getStatus();
								}
								resetResultTableData();
							}
						}
					}

					runTime++;

					// 正在运行进程
					processJcbs = readyJcbs;

					if (runJcb != null) {
						if (runTime == runJcb.getServiceTime()) {
							runTime = 0;
							readyJcbs.remove(runJcb);
							if (readyJcbs.size() == 1) {
								readyRows = new String[1][4];
							}

							int end = -1;
							for (int i = 0; i < 4; i++) {
								if (jcbs.get(i).getName()
										.equals(runJcb.getName())) {
									end = i;
									break;
								}
							}
							resultRows[end][3] = String.valueOf(jcbs.get(end)
									.getBeginTime());
							resultRows[end][4] = jcbs.get(end).getFinishTime()
									.toString();
							jcbs.get(end).setStatus("F");
							resultRows[end][6] = jcbs.get(end).getStatus();
							resultRows[end][7] = String.valueOf(jcbs.get(end)
									.getCircleTime());
							resultRows[end][8] = jcbs.get(end)
									.getAvgCircleTime();

							if (num < 2) {
								jcbs.get(num + 2).setStatus("R");
								resultRows[num + 2][6] = jcbs.get(num + 2)
										.getStatus();
							}
							resetResultTableData();
							resetReadyTableData();
							runJcb = null;
							num++;
						} else {
							resetProcessTableData();
						}
					} else {
						if (processJcbs.size() != 0) {
							Priority.priority(processJcbs);
							processJcbs.get(0).setBeginTime(time);
							runJcb = processJcbs.get(0);
							resetProcessTableData();
						} else {
							finished = true;
							resultTableTimer.purge();
							processRows = null;
							processTableModel = (DefaultTableModel) processTable
									.getModel();
							processTableModel.setDataVector(processRows,
									processColumns);
							processTable.validate();
							processTable.updateUI();

							readyRows = null;
							readyTableModel = (DefaultTableModel) readyTable
									.getModel();
							readyTableModel.setDataVector(readyRows,
									readyColumns);
							readyTable.validate();
							readyTable.updateUI();

							int sumZZ = 0;
							int sumDQZZ = 0;
							for (int i = 0; i < 4; i++) {
								sumZZ += jcbs.get(i).getCircleTime();
								sumDQZZ += Double.parseDouble(jcbs.get(i)
										.getAvgCircleTime());
							}
							avgZZ.setText(String.valueOf(sumZZ / 4.0));
							avgDQZZ.setText(String.valueOf(sumDQZZ / 4.0));
						}
					}
					time++;
				}
			}, 0, 1000);
		} else if (e.getSource() == randButton) {
			if (clicked) {
				JOptionPane.showMessageDialog(null, "已分配作业", "温馨提示",
						JOptionPane.INFORMATION_MESSAGE);
			} else {
				clicked = true;
				randPcbs();
				resetRandTableData();
			}
		}
	}

	private void randPcbs() {
		jcbs = RandUtil.generator();
		for (int i = 0; i < 4; i++) {
			randRows[i][0] = jcbs.get(i).getName();
			randRows[i][1] = jcbs.get(i).getArrivalTime().toString();
			randRows[i][2] = jcbs.get(i).getServiceTime().toString();
			randRows[i][3] = jcbs.get(i).getPriority().toString();
		}
	}

	private void resetRandTableData() {
		randTableModel = (DefaultTableModel) randTable.getModel();
		randTableModel.setDataVector(randRows, randColumns);
		randTable.validate();
		randTable.repaint();
	}

	private void resetResultTableData() {
		defaultTableModel = (DefaultTableModel) resultTable.getModel();
		defaultTableModel.setDataVector(resultRows, resultColumns);
		resultTable.validate();
		resultTable.updateUI();
	}

	private void resetReadyTableData() {
		for (int j = 0; j < readyJcbs.size(); j++) {
			readyRows[j][0] = readyJcbs.get(j).getName();
			readyRows[j][1] = readyJcbs.get(j).getServiceTime().toString();
			readyRows[j][2] = readyJcbs.get(j).getPriority().toString();
			readyRows[j][3] = readyJcbs.get(j).getStatus();
		}
		readyTableModel = (DefaultTableModel) readyTable.getModel();
		readyTableModel.setDataVector(readyRows, readyColumns);
		readyTable.validate();
		readyTable.updateUI();
	}

	private void resetProcessTableData() {
		processRows[0][0] = runJcb.getName();
		processRows[0][1] = runJcb.getServiceTime().toString();
		processRows[0][2] = String.valueOf(runJcb.getBeginTime());
		processRows[0][3] = String.valueOf(runTime);
		processRows[0][4] = String.valueOf(runJcb.getServiceTime() - runTime);
		processRows[0][5] = runJcb.getPriority().toString();
		processTableModel = (DefaultTableModel) processTable.getModel();
		processTableModel.setDataVector(processRows, processColumns);
		processTable.validate();
		processTable.updateUI();
	}

	public static void main(String[] args) {
		LaunchFrame launchFrame = new LaunchFrame();
		launchFrame.init();
	}

}
